// Copyright 2013 Tumblr, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package teleport implements a transport layer that can overcome network outages without affecting the endpoints
package teleport

import (
	"strconv"
	"strings"
)

// Addr represents an abstract endpoint undress in the form of a string.
// Specific transport implementations will be responsible for interpreting this string.
type Addr string

// Port returns the port number embedded in the address
func (addr Addr) Port() int {
	i := strings.Index(string(addr), ":")
	if i < 0 {
		panic("endpoint address has no port")
	}
	port, err := strconv.Atoi(string(addr)[i+1:])
	if err != nil {
		panic("endpoint address with invalid port")
	}
	return port
}

// Conn represents an abstract connection interface.
type Conn interface {

	// Read reads the next native Go object from the connection
	Read() (interface{}, error)

	// Write writes a native Go object to the connection
	Write(interface{}) error

	// Close closes the connection
	Close() error

	// RemoteAddr returns the address of the remote endpoint
	RemoteAddr() Addr
}

// Listener is an abstract listening interface that can receive incoming connections.
type Listener interface {
	// Accept blocks and returns the next incoming connection.
	Accept() Conn
}

// Dialer is an abstract dialing interface that can establish connections to remote endpoints, given by address.
type Dialer interface {
	// Dial establishes a new connection to the remote behind addr.
	Dial(addr Addr) Conn
}

// Transport is a combination of a listening and dialing interface.
type Transport interface {
	Dialer
	Listener
}
